
import { getRoomDomain } from "../global/map";
import { getActualFreeCapacity, getActualResourceAmount, transportResource } from "../util/store";
import { jobGoto } from "./goto";
import { jobTransfer } from "./transfer";

export const jobWithdraw={
    
    /**
     * 
     * @param {Room} mainRoom 
     * @returns {(Creep|Tombstone|Resource|Ruin)[]}
     */
    getTargets(mainRoom){
        if(mainRoom.__withdrawTargets !== undefined){
            return mainRoom.__withdrawTargets;
        }

        let domain = getRoomDomain(mainRoom, true);


        let targets=[];
        for(let roomName of domain){
            let room = Game.rooms[roomName];
            if(!room){
                continue;
            }
            targets.push(...room.find(FIND_MY_CREEPS,{
                filter:(creep)=>{
                    return  creep.memory.role==='harvester' &&
                        (
                            creep.store[RESOURCE_ENERGY]>100||
                            creep.store[RESOURCE_ENERGY]/creep.store.getCapacity()>.50
                        );
                }
            }));
            targets.push(...room.find(FIND_TOMBSTONES,{
                filter(tombstone){
                    return tombstone.store.getUsedCapacity(RESOURCE_ENERGY)>=50;
                }
            }));
            targets.push(...room.find(FIND_RUINS,{
                filter(ruin){
                    return ruin.store[RESOURCE_ENERGY]>=50;
                }
            }));
            targets.push(...room.find(FIND_DROPPED_RESOURCES,{
                filter(resource){
                    return resource.amount>=200;
                }
            }));
        }

        if(targets.length>0 && jobTransfer.isStoring(mainRoom)){
            return mainRoom.__withdrawTargets = targets;
        }

        for(let roomName of domain){
            let room = Game.rooms[roomName];
            if(!room){
                continue;
            }
            targets.push(...room.find(FIND_STRUCTURES,{
                filter(structure){
                    if(!structure.store){
                        return false;
                    }
                    if(structure.store[RESOURCE_ENERGY] === 0){
                        return false;
                    }
                    if(structure instanceof StructureStorage && structure.my){
                        return true;
                    }
                    // if(structure instanceof StructureContainer){
                    //     return true;
                    // }
                    return false;
                }
            }));
        }

        const isStorage = (structure)=>{
            return [STRUCTURE_STORAGE,STRUCTURE_CONTAINER].some((type)=>type === structure.structureType);
        };
        return mainRoom.__withdrawTargets = targets.sort((a,b)=>{
            let intA = isStorage(a)?0:1;
            let intB = isStorage(b)?0:1;
            return intA - intB;
        });
    },
    /**
     * 
     * @param {AnyCreep} creep 
     * @param {AnyCreep[]|AnyStoreStructure[]} targets
     * @param {MoveToOpts} opts
     * @returns {CreepActionReturnCode}
     */
    run(creep, targets=undefined, opts=undefined, soleTarget = false, shortTerm = false){
        if(opts===undefined){
            opts = {visualizePathStyle:{stroke:"#00ffff"}};
        }else if(opts.visualizePathStyle === undefined){
            opts.visualizePathStyle={stroke:"#00ffff"};
        }
        if(targets===undefined){
            let mainRoomName=creep.room.memory.mainRoomName;
            targets=this.getTargets(Game.rooms[mainRoomName]);
        }
        if(targets.length === 0){
            return ERR_NOT_FOUND;
        }
        // let freeCapacity=creep.store.getFreeCapacity();
        jobGoto.sortTargetsByDistance(creep, targets);
        let ret = ERR_NOT_FOUND;
        

        let c=-1;
        for(let i=0; i<targets.length; i++){
            let target = targets[i];

            if(getActualFreeCapacity(creep) === 0){
                ret = OK;
                break;
            }
            let ret0;
            if(creep.memory.goto && creep.memory.goto.target === target.id){
                ret0 = transportResource(target, creep, RESOURCE_ENERGY, undefined, shortTerm);
            }else{
                ret0 = transportResource(target, creep, RESOURCE_ENERGY, undefined, true);
            }

            if(ret0 === ERR_NOT_ENOUGH_ENERGY && getActualResourceAmount(target, RESOURCE_ENERGY) === 0){
                targets.splice(i,1);
                i--;
            }else{
                ret = ret0;
            }

            if(c===-1){
                c=i;
            }

            if(soleTarget){
                break;
            }
        }

        if(c===-1){
            c=0;
        }else if(getActualResourceAmount(targets[c]) === 0){
            targets.splice(c, 1);
        }
        if(targets.length > 0){
            jobGoto.run(creep, targets, opts);
        }
        return ret;
    }
}